﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.ComponentModel;
using ScrumTable.Common;
using ScrumTable.Common.Collections;
using ScrumTable.Common.Security;
using ScrumTable.Common.Threading;
using ScrumTable.DL.Data.Common;
using ScrumTable.BL.DM.DataManagement.Tracking;

#endregion

namespace ScrumTable.BL.DM.DataManagement
{
    /// <summary>
    /// Contains all data used by the domain layer, this is the entry
    /// point for the domain layer and contains all required business
    /// objects in order to manage data from a data source.
    /// </summary>
    public interface IDomainContext : IDisposableObject
    {
        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------

        /// <summary>
        /// Returns true if the external sysetem is connected and can be used.
        /// </summary>
        bool IsConnected { get; }

        /// <summary>
        /// Gets a list of all project.
        /// </summary>
        DomainCollection<Project> Projects { get; }

        /// <summary>
        /// Gets the current connection state.
        /// </summary>
        ConnectionState ConnectionState { get; }

        /// <summary>
        /// Gets the connection information which are provided by the user
        /// and used to establish a connection to the external data services.
        /// </summary>
        ConnectionInformation ConnectionInformation { get; }

        /// <summary>
        /// Gets the underlying undo manager which is needed to track
        /// the state of the business layer entities.
        /// </summary>
        UndoManager UndoManager { get; }

        /// <summary>
        /// Gets additional driver information from the underlying data layer.
        /// </summary>
        DomainDriverInformation DriverInfo { get; }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// Connects to the server instance. Make sure you disconnect from the
        /// server after you finished your work with the data connection.
        /// </summary>
        /// <param name="dispatcher">Specifies the sychronization dispatcher for the async callback.</param>
        /// <param name="credentials">Specifies the connection context which provides information about the end system and the user.</param>
        /// <param name="callback">Specifies the callback used to retrieve the connection state.</param>
        /// <param name="dataMoniker">Specifies a hint (moniker) to the data location. This must be supported by the underlying driver.</param>
        void Connect(IDataSyncDispatcher dispatcher, ConnectionInformationManager credentials, AsyncCallback callback, string dataMoniker);

        /// <summary>
        /// Changes the user and stores its changes to the back end system.
        /// </summary>
        /// <param name="credentials">Specifies the login credential information.</param>
        /// <param name="callbackEvent">Specifies the callback which is fired after the
        /// process has been completed. The callback is of type ICancellableDataResult
        /// and its Data property contains true, if all changes have been accepted.</param>
        void ChangeUser(Member credentials, AsyncCallback callbackEvent);

        /// <summary>
        /// Changes the user after the latests changes have been stored to the back end system.
        /// </summary>
        /// <param name="credentials">Specifies the login credential information.</param>
        void ChangeUser(Member credentials);

        /// <summary>
        /// Disconnects from a connected server instance.
        /// </summary>
        void Disconnect();

        /// <summary>
        /// Searches in the domain context tree for a domain object with the
        /// given id/type chain and returns the found element.
        /// </summary>
        /// <param name="typedIdChain">Specifies the id chain of the element to retrieve.</param>
        /// <returns>Returns the retrieved element.</returns>
        DomainBase TryGetObjectByChain(ValueChain<Pair<string, Type>> typedIdChain);

        /// <summary>
        /// Searches in the domain context tree for a domain object wiht the
        /// given id/type chain and returns the found element.
        /// </summary>
        /// <param name="typedIdChain">Specifies the id chain of the element to retrieve.</param>
        /// <returns>Returns the retrieved element.</returns>
        T TryGetObjectByChain<T>(ValueChain<Pair<string, Type>> typedIdChain)
            where T : DomainBase, new();

        /// <summary>
        /// Searches in the domain context tree for a domain object with the
        /// given id/type chain and returns the found element.
        /// </summary>
        /// <param name="typedIdChain">Specifies the id chain of the element to retrieve.</param>
        /// <typeparam name="T">Specifies the item type of the collection to retrieve.</typeparam>
        /// <returns>Returns the retrieved element.</returns>
        DomainCollection<T> TryGetCollectionByChain<T>(ValueChain<Pair<string, Type>> typedIdChain)
            where T : DomainBase, new();

        /// <summary>
        /// Searches in the domain context tree for a domain object with the
        /// given id/type chain and returns the found element. This procedure is slower than
        /// the ValueChain&gt;Pair&gt;string, Type&lt;&lt; variant.
        /// </summary>
        /// <param name="typedIdChain">Specifies the id chain of the element to retrieve.</param>
        /// <typeparam name="T">Specifies the item type of the collection to retrieve.</typeparam>
        /// <returns>Returns the retrieved element.</returns>
        DomainCollection<T> TryGetCollectionByChain<T>(ValueChain<string> typedIdChain)
            where T : DomainBase, new();

        /// <summary>
        /// Disables the CollectionChanged event on domain context scope level.
        /// </summary>
        /// <returns>Returns a disposable object which is used to fire the result event.
        /// The Action property of this event is set to DomainCollectionChangedAction.None and
        /// the Owner and ChangedItem properties are set to null.</returns>
        IDisposable DisableCollectionChangedEvents();

        /// <summary>
        /// Disables the ElementChanging event on domain context scope level.
        /// </summary>
        /// <returns>Returns a disposable object which is used to fire the result event.
        /// The ChangedItem property is set to null and the ChangedElement contains an
        /// empty string.</returns>
        IDisposable DisableElementChangingEvents();

        /// <summary>
        /// Disables the ElementChanged event on domain context scope level.
        /// </summary>
        /// <returns>Returns a disposable object which is used to fire the result event.
        /// The ChangedItem property is set to null and the ChangedElement contains an
        /// empty string.</returns>
        IDisposable DisableElementChangedEvents();

        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------

        /// <summary>
        /// This event is fired if an synchronization error has occurred on
        /// the underlying data storage.
        /// </summary>
        event DomainSyncErrorHandler SyncError;

        /// <summary>
        /// This event is fired if an element has been added or removed from
        /// a collection.
        /// </summary>
        event DomainCollectionChangedEventHandler CollectionChanged;

        /// <summary>
        /// This event is fired before an element has been 
        /// changed from the collection.
        /// </summary>
        event PropertyChangingEventHandler ElementChanging;

        /// <summary>
        /// This event is after before an element has been 
        /// changed from the collection.
        /// </summary>
        event PropertyChangedEventHandler ElementChanged;

        #endregion
    }
}